package com.tim.javaApi.reflect;

import com.mysql.cj.jdbc.Driver;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import sun.security.ec.SunEC;

import java.beans.*;
import java.io.Serializable;
import java.lang.annotation.*;
import java.lang.reflect.*;
import java.sql.SQLException;
import java.util.*;

/**
 * @Description:
 * @Version 1.0, 2021/9/24
 * @Author Tim
 */
public class ReflectApi {

    /**
     *
     */
    public static void concept() throws IntrospectionException {
        Method method;

        Introspector introspector;
        BeanInfo beanInfo = Introspector.getBeanInfo(StringBuilder.class);
        PropertyDescriptor propertyDescriptor;
        MethodDescriptor methodDescriptor;

    }

    /**
     * 代理：静态代理、java动态代理、cglib动态代理
     */
    public static void proxy(){
        // 静态代理；继承接口、组合源对象

        // java动态代理。构建接口代理类；通过InvocationHandler参数构造器构建对象
        // Proxy构建代理类，无源对象；InvocationHandler组合源对象，反射调用方法
        InvocationHandler invocationHandler;// 类似静态代理，组合源对象；通过method直接执行方法
        Proxy proxy;// 门面模式，提供统一访问

        // cglib
        Enhancer enhancer;
        MethodInterceptor methodInterceptor;

    }

    public void classLoader() throws SQLException {
        ClassLoader classLoader;
        // bootstrap 输出为null
        Object object = new Object();
        System.out.println(object.getClass().getClassLoader());
        object = new String();
        System.out.println(object.getClass().getClassLoader());
        // ext
        object = new SunEC();
        System.out.println(object.getClass().getClassLoader());
        // app
        object = new ReflectApi();
        System.out.println(object.getClass().getClassLoader());
        // app
//        object = new AdminParamResp();
//        System.out.println(object.getClass().getClassLoader());
        // app，bootstrap委托给线程上下文加载器加载
        object = new Driver();
        System.out.println(object.getClass().getClassLoader());

    }

    public static void classTypeGeneric() throws NoSuchFieldException {
        /*
         * 表示java中的类、接口
         *  枚举为类，注解为接口(Annotation)
         *  数组归属一个类。Array？
         *  基本类型、void；也为类。int.class，void.class
         */
        Class clz = Object.class;
        {
            Method[] method=clz.getMethods();
            Field[] field=clz.getFields();
            Constructor[] constructor=clz.getConstructors();
            // 注解基类
            Annotation annotation=clz.getAnnotation(Inherited.class);
            // 数组。获取数组元素类型
            Array array;
            clz.isArray();
            Class componentType = clz.getComponentType();
            // 修饰符
            int modifiers = clz.getModifiers();

            System.out.println("class-------------");
            System.out.println(Object[].class.getName());
            System.out.println(int[].class.getName());
            System.out.println(int[].class.getSuperclass().getName());
            System.out.println(int[].class.getComponentType().getName());
            System.out.println(void.class.getName());
            System.out.println(int.class.getName());
        }
        /*
         * java中的类型
         * 包括：对象类型、基本类型、数组类型、泛型类型、类型变量
         * https://blog.csdn.net/ShuSheng0007/article/details/89520530
         */
        Type type;
        {
            // 泛型数组类型。List<T>[]、T[]
            GenericArrayType t1;
            // 参数化类型。List<T>
            ParameterizedType t2;
            // 类型变量。List<T>、List<T extend Number>中的T
            TypeVariable t3;
            // 通配符类型，extend、super。List<? extend Number>中的?
            WildcardType t4;
            Class t5;// 实现类

            System.out.println("type-------------");
            Field v = TypeTest.class.getField("v");
            TypeVariable tv = (TypeVariable) v.getGenericType();
            System.out.println(tv.getName());// 类型名称
            System.out.println(Arrays.asList(tv.getBounds()));// 类型上界
            System.out.println(tv.getGenericDeclaration());// 声明泛型的载体

            Field map = TypeTest.class.getField("map");
            ParameterizedType pt = (ParameterizedType) map.getGenericType();
            System.out.println(Arrays.asList(pt.getActualTypeArguments()));// 泛型参数列表
            System.out.println(pt.getRawType());// 原始类型
            System.out.println(pt.getOwnerType());// 外部类 or null

            Field tArray = TypeTest.class.getField("tArray");
            GenericArrayType gat = (GenericArrayType) tArray.getGenericType();
            System.out.println(gat.getTypeName());
            System.out.println(gat.getGenericComponentType().getTypeName());

            Field mapWithWildcard = TypeTest.class.getField("mapWithWildcard");
            ParameterizedType pt2 = (ParameterizedType) mapWithWildcard.getGenericType();
            Type[] wts = pt2.getActualTypeArguments();
            System.out.println(Arrays.asList(((WildcardType)wts[0]).getLowerBounds()));// 下界
            System.out.println(Arrays.asList(((WildcardType)wts[1]).getUpperBounds()));// 上界

        }

    }

    public void getGenericClass() {
        // 继承/实现非泛型父级
        List<Integer> list = new ArrayList<Integer>(){};
        // 拿不到泛型类型
//        List<Integer> list = new ArrayList<Integer>();
        Class clazz = list.getClass();
        ParameterizedType parameterizedType = (ParameterizedType) clazz.getGenericSuperclass();
        Type[] types = parameterizedType.getActualTypeArguments();
        System.out.println(types[0]);
    }

    public static void main(String[] args) throws Exception {
//        List<Integer> list = new ArrayList<Integer>(){};
        List<Integer> list = new ArrayList<Integer>();
        Class clazz = list.getClass();
        ParameterizedType parameterizedType = (ParameterizedType) clazz.getGenericSuperclass();
        Type[] types = parameterizedType.getActualTypeArguments();
        System.out.println(types[0]);

        classTypeGeneric();
    }

    @Retention(RetentionPolicy.RUNTIME)
    @Target(value = {ElementType.ANNOTATION_TYPE,
            ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE_USE})
    public @interface Custom {
    }

    public static class TypeTest<T, V extends @Custom Number & Serializable> {
        private Number number;
        public T t;
        public V v;
        public List<T> list = new ArrayList<>();
        public Map<String, T> map = new HashMap<>();

        public T[] tArray;
        public List<T>[] ltArray;

        public TypeTest testClass;
        public TypeTest<T, Integer> testClass2;

        public Map<? super String, ? extends Number> mapWithWildcard;

        //泛型构造函数,泛型参数为X
        public <X extends Number> TypeTest(X x, T t) {
            number = x;
            this.t = t;
        }

        //泛型方法，泛型参数为Y
        public <Y extends T> void method(Y y) {
            t = y;
        }
    }

}
